/*
 *  Copyright 2013 National Institute of Advanced Industrial Science and Technology
 *  
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.sss.mapreduce.benchmark;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

public class IoCompositeProperties {
  CommandLine cl;
  Properties prop;
  int initialKeyCount = 10;
  int initialValueLength = 200;
  int mappedKeyCount = 1000;
  int mappedUniqueKeyCount = 256;
  int mappedValueLength = 20;
  int reducedValueLength = 20;
//  int defaultBlockSize = 1024 * 1024;
  String partitionMethod = new String("average");
  boolean combinerEnabled = false;

  private void ResetProperties() {
    prop = new Properties();
    prop.setProperty("initialKeyCount", Integer.toString(getInitialKeyCount()));
    prop.setProperty("initialValueLength", Integer.toString(getInitialValueLength()));
    prop.setProperty("mappedKeyCount", Integer.toString(getMappedKeyCount()));
    prop.setProperty("mappedUniqueKeyCount", Integer.toString(getMappedUniqueKeyCount()));
    prop.setProperty("mappedValueLength", Integer.toString(getMappedValueLength()));
    prop.setProperty("reducedValueLength", Integer.toString(getReducedValueLength()));
    prop.setProperty("partitionMethod", getPartitionMethod());
    prop.setProperty("combinerEnabled", Boolean.toString(getCombinerEnabled()));
  }

  private void init(CommandLine cl) {
    if (cl == null)
      return;

    String opt;
    opt = cl.getOptionValue("initialKeyCount");
    if (opt != null)
      initialKeyCount = Integer.parseInt(opt);
    opt = cl.getOptionValue("initialValueLength");
    if (opt != null)
      initialValueLength = Integer.parseInt(opt);
    opt = cl.getOptionValue("mappedKeyCount");
    if (opt != null)
      mappedKeyCount = Integer.parseInt(opt);
    opt = cl.getOptionValue("mappedUniqueKeyCount");
    if (opt != null)
      mappedUniqueKeyCount = Integer.parseInt(opt);
    opt = cl.getOptionValue("mappedValueLength");
    if (opt != null)
      mappedValueLength = Integer.parseInt(opt);
    opt = cl.getOptionValue("reducedValueLength");
    if (opt != null)
      reducedValueLength = Integer.parseInt(opt);
    opt = cl.getOptionValue("partitionMethod");
    if (opt != null)
      partitionMethod = opt;
    opt = cl.getOptionValue("combinerEnabled");
    if (opt != null)
      combinerEnabled = Boolean.parseBoolean(opt);
  }

  private void init(String confFile, CommandLine cl) {
    prop = new Properties();
    if (confFile == null) {
      prop.setProperty("initialKeyCount", Integer.toString(getInitialKeyCount()));
      prop.setProperty("initialValueLength", Integer.toString(getInitialValueLength()));
      prop.setProperty("mappedKeyCount", Integer.toString(getMappedKeyCount()));
      prop.setProperty("mappedUniqueKeyCount", Integer.toString(getMappedValueLength()));
      prop.setProperty("mappedValueLength", Integer.toString(getMappedValueLength()));
      prop.setProperty("reducedValueLength", Integer.toString(getReducedValueLength()));
      prop.setProperty("partitionMethod", getPartitionMethod());
      prop.setProperty("combinerEnabled", Boolean.toString(getCombinerEnabled()));
    } else {
      try {
        InputStream stream = new FileInputStream(confFile);
        prop.loadFromXML(stream);
        stream.close();
      } catch (IOException e) {
        System.err.println(e.getMessage());
        System.exit(1);
      }
    }

   initialKeyCount      = Integer.parseInt(prop.getProperty("initialKeyCount", "10"));
   initialValueLength   = Integer.parseInt(prop.getProperty("initialValueLength", "200"));
   mappedKeyCount       = Integer.parseInt(prop.getProperty("mappedKeyCount", "1000"));
   mappedUniqueKeyCount = Integer.parseInt(prop.getProperty("mappedUniqueKeyCount", "256"));
   mappedValueLength    = Integer.parseInt(prop.getProperty("mappedValueLength", "20"));
   reducedValueLength   = Integer.parseInt(prop.getProperty("reducedValueLength", "20"));
   partitionMethod      = prop.getProperty("partitionMethod", "average");
   combinerEnabled      = Boolean.parseBoolean(prop.getProperty("combinerEnabled", "false"));

    init(cl);
    ResetProperties();
  }

  public IoCompositeProperties(String confFile) {
    System.out.println("IoCompositeProperties#IoCompositeProperties(String)");
    init(confFile, null);
  }

  public IoCompositeProperties(String[] args) {
    System.out.println("IoCompositeProperties#IoCompositeProperties(String[])");
    Options options = new Options();
    options.addOption("conf", true, "Configuration file");
    options.addOption("initialKeyCount", true, "initialKeyCount");
    options.addOption("initialValueLength", true, "initialValueLength");
    options.addOption("mappedKeyCount", true, "mappedKeyCount");
    options.addOption("mappedUniqueKeyCount", true, "mappedUniqueKeyCount");
    options.addOption("mappedValueLength", true, "mappedValueLength");
    options.addOption("reducedValueLength", true, "reducedValueLength");
    options.addOption("partitionMethod", true, "partitionMethod");
    options.addOption("combinerEnabled", true, "combinerEnabled");

    try {
      cl = new BasicParser().parse(options, args);
    } catch (ParseException e) {
      System.err.println(e.getMessage());
      System.exit(1);
    }
    init(cl.getOptionValue("conf"), cl);
  }

  public String[] getArgs() {
    return cl.getArgs();
  }

  public Properties getProperties() {
    return prop;
  }

  int getInitialKeyCount() {
    return initialKeyCount;
  }

  int getInitialValueLength() {
    return initialValueLength;
  }

  int getMappedKeyCount() {
    return mappedKeyCount;
  }

  int getMappedValueLength() {
    return mappedValueLength;
  }

  int getMappedUniqueKeyCount() {
    return mappedUniqueKeyCount;
  }

  int getReducedValueLength() {
    return reducedValueLength;
  }

  String getPartitionMethod() {
    return partitionMethod;
  }

  boolean getCombinerEnabled() {
    return combinerEnabled;
  }
}
